package speedchina.controller.work;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import speedchina.controller.BaseController;
import speedchina.dto.WeekDTO;
import speedchina.dto.WorkHourParamDTO;
import speedchina.entity.BaseEntity;
import speedchina.entity.user.Dept;
import speedchina.entity.user.Post;
import speedchina.entity.user.User;
import speedchina.entity.work.Project;
import speedchina.entity.work.ProjectType;
import speedchina.entity.work.WorkHour;
import speedchina.service.user.DeptService;
import speedchina.service.user.PostService;
import speedchina.service.user.UserService;
import speedchina.service.work.ProjectService;
import speedchina.service.work.ProjectTypeService;
import speedchina.service.work.WorkHourService;
import speedchina.util.ExcelUtil;
import speedchina.util.WeekUtils;
import speedchina.vo.LayuiTableVO;
import speedchina.vo.ResultVO;
import speedchina.vo.workhour.WorkHourTableVO;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 工时
 *
 * @author earthchen
 * @date 2018/9/29
 **/
@Controller
@RequestMapping("/workhours")
public class WorkHoursController extends BaseController
{

    private Logger logger = LoggerFactory.getLogger(WorkHoursController.class);

    @Autowired
    private WorkHourService workHourService;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private PostService postService;

    @Autowired
    private UserService userService;

    @Autowired
    private DeptService deptService;

    @Autowired
    private ProjectTypeService projectTypeService;

    /**
     * 工时页面
     *
     * @return
     */
    @RequiresPermissions("system:workhours:view")
    @GetMapping("/view")
    public String workhours(Model model)
    {
        List<Project> projectList = projectService.list(
            new QueryWrapper<Project>()
                .eq("status", "0")
                .eq("del_flag", "0"));

        List<ProjectType> projectTypeList = projectTypeService.list(new QueryWrapper<>());
        model.addAttribute("projectList", projectList);
        model.addAttribute("typeList", projectTypeList);
        return "workhour/myworkhour";
    }

    /**
     * 领导或管理员查看页面
     *
     * @param model
     * @return
     */
    @GetMapping("/admin")
    @RequiresPermissions("system:workhours:adminview")
    public String adminWorkHour(Model model)
    {
        List<Project> projectList = projectService.list(
            new QueryWrapper<Project>()
                .eq("status", "0")
                .eq("del_flag", "0"));
        List<ProjectType> projectTypeList = projectTypeService.list(new QueryWrapper<>());
        model.addAttribute("projectList", projectList);
        model.addAttribute("typeList", projectTypeList);
        return "workhour/admin";
    }

    /**
     * 分页获取自己工时数据
     *
     * @param paramDTO
     * @return
     */
    @RequiresPermissions("system:workhours:list")
    @GetMapping("/view/me")
    @ResponseBody
    public LayuiTableVO list(WorkHourParamDTO paramDTO)
    {
        Page<WorkHour> page = new Page<>(paramDTO.getPage(), paramDTO.getSize());
        WeekDTO weekDTO = new WeekDTO();
        if (paramDTO.getStartDate() == null && paramDTO.getEndDate() == null)
        {
            weekDTO = WeekUtils.getWeekDays(paramDTO.getWeekCode());
        }
        else
        {
            weekDTO.setStartDate(paramDTO.getStartDate());
            weekDTO.setEndDate(paramDTO.getEndDate());
        }

        QueryWrapper<WorkHour> entityWrapper = new QueryWrapper<WorkHour>()
            .eq(getUser() != null, "user_id", getUserId())
            .eq("del_flag", "0")
            .between("work_date", weekDTO.getStartDate(), weekDTO.getEndDate());
        // 获取本周工时
        if (paramDTO.getProjectId() != null)
        {
            entityWrapper.eq("project_id", paramDTO.getProjectId());
        }
        workHourService.page(page, entityWrapper);
        List<WorkHour> workHourList = page.getRecords();
        List<WorkHourTableVO> workHourTableVOS = new ArrayList<>();
        for (WorkHour workHour : workHourList)
        {
            WorkHourTableVO workHourTableVO = new WorkHourTableVO();
            BeanUtils.copyProperties(workHour, workHourTableVO);
            // 设置周几
            workHourTableVO.setWeekHour();
            workHourTableVOS.add(workHourTableVO);
        }
        return getTableInfo(workHourTableVOS, page.getTotal());
    }

    /**
     * 管理员或者部门经理查看自己部门员工的工时
     *
     * @param paramDTO
     * @return
     */
    @RequiresPermissions("system:workhours:adminlist")
    @ResponseBody
    @GetMapping("/admin/view")
    public LayuiTableVO view(WorkHourParamDTO paramDTO)
    {
        Page<WorkHour> page = new Page<>(paramDTO.getPage(), paramDTO.getSize());
        WeekDTO weekDTO = new WeekDTO();
        if (paramDTO.getStartDate() == null && paramDTO.getEndDate() == null)
        {
            weekDTO = WeekUtils.getWeekDays(paramDTO.getWeekCode());
        }
        else
        {
            weekDTO.setStartDate(paramDTO.getStartDate());
            weekDTO.setEndDate(paramDTO.getEndDate());
        }

        // 构造实体包装类
        QueryWrapper<WorkHour> entityWrapper = new QueryWrapper<WorkHour>()
            .eq("del_flag", "0")
            .between("work_date", weekDTO.getStartDate(), weekDTO.getEndDate());

        if (paramDTO.getProjectId() != null)
        {
            entityWrapper.eq("project_id", paramDTO.getProjectId());
        }
        // 判断是不是当官的
        isManager(entityWrapper);
        //获得已经删除的用户
        QueryWrapper<User> userWrapper = new QueryWrapper<User>();
        userWrapper.eq("del_flag","1");
        List<User> delUserList=userService.list(userWrapper);
        entityWrapper.notIn("user_id",delUserList.stream().map(User::getUserId).collect(Collectors.toSet()));
        workHourService.page(page, entityWrapper);
        List<WorkHour> workHourList = page.getRecords();

        // 当前所有被查询到的用户列表
        List<User> userList = userService.list(new QueryWrapper<User>()
            .in("id",
                workHourList.stream().map(WorkHour::getUserId).collect(Collectors.toSet()))

        );
        // 构造id-user映射map
        Map<Long, User> map = userList.stream().collect( Collectors.toMap(User::getId, user -> user));

        List<WorkHourTableVO> workHourTableVOS = new ArrayList<>();
        for (WorkHour workHour : workHourList)
        {
            WorkHourTableVO workHourTableVO = new WorkHourTableVO();
            BeanUtils.copyProperties(workHour, workHourTableVO);
            // 设置用户名
            workHourTableVO.setUsername(map.get(workHour.getUserId()).getUserName());
            // 设置周几
            workHourTableVO.setWeekHour();
            workHourTableVOS.add(workHourTableVO);
        }

        return getTableInfo(workHourTableVOS, page.getTotal());
    }

    /**
     * 判断是否当官的
     *
     * @return
     */
    private void isManager(QueryWrapper<WorkHour> entityWrapper)
    {
        // 是否当官的标志
        boolean isManager = false;
        // 判断当前是否是管理员
        if (!getUserId().equals(1L))
        {
            // 判断当前是不是当官的(不是员工)
            List<Post> postList = postService.selectPostsByUserId(getUserId());
            for (Post post : postList)
            {
                // 如果有一个岗位不是用户，那么就是当官的
                if (!"user".equals(post.getPostCode()))
                {
                    isManager = true;
                    break;
                }
            }
            // 保存当前部门层级下所有用户信息
            List<User> deptUserList = new ArrayList<>();
            // 如果是当官的
            if (isManager)
            {
                String deptId = getUser().getDeptId();
                getDeptUser(deptId, deptUserList);
            }
            // 所有用户的id
            List<Long> userIdList = deptUserList.stream().map(BaseEntity::getId).collect(Collectors.toList());
            entityWrapper.in("user_id", userIdList);
        }
    }

    /**
     * 递归获取当前层级下所有用户的列表
     *
     * @param deptId       当前部门id
     * @param deptUserList 部门层级下的用户列表
     */
    private void getDeptUser(String deptId, List<User> deptUserList)
    {
        List<User> users = userService.list(new QueryWrapper<User>()
            .eq(deptId!=null,"dept_id", deptId));
        if (users.isEmpty())
        {
            return;
        }
        // 加入用户列表
        deptUserList.addAll(users);
        List<Dept> childDept = deptService.getChildrenDept(deptId);
        Set<Long> deptIdList = childDept.stream().map(BaseEntity::getId).collect(
            Collectors.toSet());

        for (Long id : deptIdList)
        {
            getDeptUser(id.toString(), deptUserList);
        }
    }

    /**
     * 批量增加工时
     *
     * @return
     */
    @RequiresPermissions("system:workhours:add")
    @PostMapping(value = "/add")
    @ResponseBody
    public ResultVO add(@RequestBody @Valid List<WorkHourTableVO> workHourTableVOS)
    {
        List<WorkHour> workHourList = new ArrayList<>();
        for (WorkHourTableVO workHourTableVO : workHourTableVOS)
        {
            // 将当前星期几填写的工时赋值给工时字段
//            workHourTableVO.weekToDayHour();
            WorkHour workHour = new WorkHour();
            BeanUtils.copyProperties(workHourTableVO, workHour);
            // 如果userid为空，说明为新增的
            if (workHour.getUserId() == null)
            {
                workHour.setUserId(getUserId());
            }
            workHourList.add(workHour);
        }
        return ResultVO.success(workHourService.saveOrUpdateBatch(workHourList));
    }

    /**
     * 更新工时
     *
     * @param workHour
     * @return
     */
    @RequiresPermissions("system:workhours:edit")
    @PutMapping("/update/{workHourId}")
    @ResponseBody
    public ResultVO update(@PathVariable("workHourId") Long workHourId, WorkHour workHour)
    {
        workHour.setId(workHourId);
        workHour.setUpdateTime(new Date());
        return ResultVO.success(workHourService.updateById(workHour));
    }

    /**
     * 删除指定id的工时
     *
     * @param workHourId
     * @return
     */
    @RequiresPermissions("system:workhours:delete")
    @DeleteMapping("/del/{workHourId}")
    @ResponseBody
    public ResultVO del(@PathVariable("workHourId") Long workHourId)
    {
        return ResultVO.success(workHourService.removeById(workHourId));
    }

    /**
     * 管理员删除指定id的工时(逻辑删除)
     *
     * @param workHourId
     * @return
     */
    @RequiresPermissions("system:workhours:admindelete")
    @DeleteMapping("/admin/del/{workHourId}")
    @ResponseBody
    public ResultVO adminDel(@PathVariable("workHourId") Long workHourId)
    {
        WorkHour workHour = new WorkHour();
        workHour.setId(workHourId);
        workHour.setDelFlag("1");
        return ResultVO.success(workHourService.updateById(workHour));
    }

    /**
     * 管理员批量删除指定id的工时(逻辑删除)
     *
     * @param idList
     * @return
     */
    @RequiresPermissions("system:workhours:batchdelete")
    @DeleteMapping("/admin/batch/del")
    @ResponseBody
    public ResultVO adminBatchDel(@RequestBody List<Long> idList)
    {
        List<WorkHour> workHourList = idList.stream().map(id -> {
            WorkHour workHour = new WorkHour();
            workHour.setId(id);
            workHour.setDelFlag("1");
            return workHour;
        }).collect(Collectors.toList());

        return ResultVO.success(workHourService.updateBatchById(workHourList));
    }

    /**
     * 管理员导出
     */
    @RequiresPermissions("system:workhours:adminexcel")
    @GetMapping("/admin/excel")
    public void adminExportData(WorkHourParamDTO paramDTO,
                                HttpServletResponse response)
    {

        WeekDTO weekDTO = new WeekDTO();
        if (paramDTO.getStartDate() == null && paramDTO.getEndDate() == null)
        {
            weekDTO = WeekUtils.getWeekDays(paramDTO.getWeekCode());
        }
        else
        {
            weekDTO.setStartDate(paramDTO.getStartDate());
            weekDTO.setEndDate(paramDTO.getEndDate());
        }

        // 构造实体包装类
        QueryWrapper<WorkHour> entityWrapper = new QueryWrapper<WorkHour>()
            .eq("del_flag", "0")
            .between("work_date", weekDTO.getStartDate(), weekDTO.getEndDate());

        if (paramDTO.getProjectId() != null)
        {
            entityWrapper.eq("project_id", paramDTO.getProjectId());
        }
        // 判断是否当官
        // 是否当官的标志
        isManager(entityWrapper);
        //获得已经删除的用户
        QueryWrapper<User> userWrapper = new QueryWrapper<User>();
        userWrapper.eq("del_flag","1");
        List<User> delUserList=userService.list(userWrapper);
        entityWrapper.notIn("user_id",delUserList.stream().map(User::getUserId).collect(Collectors.toSet()));

        List<WorkHour> workHourList = workHourService.list(entityWrapper);
        // 当前所有被查询到的用户列表
        List<User> userList = userService.list(new QueryWrapper<User>()
            .in("id",
                workHourList.stream().map(WorkHour::getUserId).collect(Collectors.toSet())));
        // 构造id-user映射map
        Map<Long, User> userMap = userList.stream().collect(
            Collectors.toMap(User::getId, user -> user));
        // 所有的项目id
        List<Long> projecIds = workHourList.stream().map(WorkHour::getProjectId).collect(
            Collectors.toList());
        // 查询所有id的项目信息
        List<Project> projectList = projectService.list(new QueryWrapper<Project>()
            .in("id", projecIds));
        // 构造id-project映射map
        Map<Long, Project> projectMap = projectList.stream().collect(
            Collectors.toMap(Project::getId, project -> project));
        // 查询所有项目类型
        List<ProjectType> typeList = projectTypeService.list(new QueryWrapper<>());
        // 构造类型id-type映射map
        Map<Long, ProjectType> typeMap = typeList.stream().collect(
            Collectors.toMap(ProjectType::getId, type -> type));

        List<WorkHourTableVO> workHourTableVOS = new ArrayList<>();
        for (WorkHour workHour : workHourList)
        {
            WorkHourTableVO workHourTableVO = new WorkHourTableVO();
            BeanUtils.copyProperties(workHour, workHourTableVO);
            // 设置用户名
            workHourTableVO.setUsername(userMap.get(workHour.getUserId()).getUserName());
            workHourTableVO.setProjectName(
                projectMap.get(workHour.getProjectId()).getProjectName());
            workHourTableVO.setProjectTypeName(
                typeMap.get(workHour.getProjectTypeId()).getTypeName());
            // 设置周几
            workHourTableVO.setWeekHour();
            workHourTableVOS.add(workHourTableVO);
        }
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("工时查看", "统计"),
            WorkHourTableVO.class, workHourTableVOS);
        try
        {
            ExcelUtil.export(response, workbook, "工时查看");
        }
        catch (Exception e)
        {
            logger.error("excel导出错误");
        }
    }

}
